﻿using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
using StarsAdmin.Application.OperationLog.Dtos;
using StarsAdmin.Application.OperationLog.Services;
using StarsAdmin.Core.App;
using StarsAdmin.Core.Exceptions;
using StarsAdmin.Core.Extensions;
using StarsAdmin.Core.Helpers;
using StarsAdmin.Core.Models;
using System.Diagnostics;
using System.Net;

namespace StarsAdmin.Web.Core.Filter
{
    /// <summary>
    /// 操作过滤器
    /// </summary>
    public class ControllerLogFilter : IAsyncActionFilter
    {
        public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
        {
            // 获取控制器/操作描述器
            var controllerActionDescriptor = context.ActionDescriptor as ControllerActionDescriptor;
            // 如果是请求登录，则跳过
            if (controllerActionDescriptor?.ActionName == "Login")
            {
                await next();
                return;
            }
            // 创建一个计时器
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();
            var actionExecutedContext = await next();
            stopwatch.Stop();
            // 获取 HttpContext 和 HttpRequest 对象
            var httpContext = context.HttpContext;
            var httpRequest = httpContext.Request;

            AddOperationLogInput logInput = new AddOperationLogInput();
            logInput.Ip = httpRequest.GetIP();
            logInput.HttpMethod = httpRequest.Method;
            logInput.ApiPath = httpRequest.Path;
            logInput.ElapsedMilliseconds = stopwatch.ElapsedMilliseconds;
            logInput.Params = context.ActionArguments.Count > 0 ? JsonHelper.Serialize(context.ActionArguments.Values) : "";
            // 客户端浏览器信息
            var userAgent = httpRequest.Headers["User-Agent"];
            if (!string.IsNullOrWhiteSpace(userAgent))
            {
                var client = UAParser.Parser.GetDefault().Parse(userAgent);
                logInput.UserAgent = userAgent.ToString();
                logInput.Device = client.Device.Family;
                logInput.Browser = client.Browser.Family;
                logInput.Os = client.OS.Family;
            }
            // 获得token
            var token = JwtHelper.GetToken(context.HttpContext);
            // 解析token
            var userId = JwtHelper.GetUserId(token);
            var userName = JwtHelper.GetUserName(token);
            if (userId != default)
            {
                logInput.UserId = userId;
            }
            if (!string.IsNullOrWhiteSpace(userName))
            {
                logInput.UserName = userName;
            }

            // 读取返回结果
            var result = actionExecutedContext.Result;
            if (result is ObjectResult objectResult)
            {
                var resultValue = objectResult.Value as ResultModel;
                if (resultValue != null)
                {
                    logInput.IsSuccess = resultValue.IsSuccess;
                    logInput.StatusCode = resultValue.Code;
                    logInput.Message = resultValue.Message;
                    //logInput.Result = JsonHelper.Serialize(resultValue.Data);
                }
            }

            // 获取异常对象情况
            var exception = actionExecutedContext.Exception;
            // 判断是否是验证异常
            if (exception != null)
            {
                switch (exception)
                {
                    case NotFoundException notFoundEx:
                        logInput.StatusCode = (int)HttpStatusCode.NotFound;
                        logInput.Message = notFoundEx.Message;
                        break;

                    case InUseException inUseEx:
                        logInput.StatusCode = (int)HttpStatusCode.Conflict;
                        logInput.Message = inUseEx.Message;
                        break;

                    default:
                        logInput.StatusCode = 500;
                        logInput.Message = exception.Message;
                        break;
                }
                logInput.IsSuccess = false;
            }
         

            // 获取服务
            var logService = AppHelper.GetService<IOperationLogService>();
            if (logService != null)
            {
                logService.AddLog(logInput);
            }
        }
    }
}